﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Casamiel.Common;
using Casamiel.Domain.Response;
using Casamiel.Domain.Response.MWeb;
using Casamiel.Domain.Response.Waimai;
using Enyim.Caching;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace Casamiel.Application.Commands
{
    /// <summary>
    /// Base command handler.
    /// </summary>
    public class BaseCommandHandler
    {
        /// <summary>
        /// 
        /// </summary>
        public INetICService NetICService { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public IHttpClientFactory HttpClientFactory { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public string Utoken { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public string MemcachedPre { get; private set; }

        /// <summary>
        /// 
        /// </summary>
        public static NLog.ILogger BizInfologger => NLog.LogManager.GetLogger("BizInfo");

        /// <summary>
        /// 
        /// </summary>
        public static NLog.ILogger LoggerSystemErrorInfo => NLog.LogManager.GetLogger("SystemErrorInfo");

        /// <summary>
        /// 
        /// </summary>
        public static NLog.ILogger Iclogger=> NLog.LogManager.GetLogger("IicApiService");
        

        /// <summary>
        /// 订单服务日志
        /// </summary>
        public static  NLog.ILogger  OrderLogger => NLog.LogManager.GetLogger("OrderService");

        /// <summary>
        /// 
        /// </summary>
        public CasamielSettings Casasettings { get; private set; }

	 
		/// <summary>
		/// 
		/// </summary>
		/// <param name="netICService"></param>
		/// <param name="httpClientFactory"></param>
		/// <param name="settings"></param>
		public BaseCommandHandler(INetICService netICService, IHttpClientFactory httpClientFactory, IOptionsSnapshot<CasamielSettings> settings)
        {
            NetICService = netICService;
            HttpClientFactory = httpClientFactory;
            if (settings== null)
            {
                throw new ArgumentNullException(nameof(settings));
            }
            Utoken = settings.Value.ApiToken;
            MemcachedPre = settings.Value.MemcachedPre;
            Casasettings = settings.Value;
			 
        }

        /// <summary>
        /// Posts the async.
        /// </summary>
        /// <returns>The async.</returns>
        /// <param name="urlstr">URL.</param>
        /// <param name="data">Data.</param>
        /// <param name="api">APIName</param>
        protected async Task<string> PostAsync(string urlstr, string data, string api = "mallapi")
        {
            var client = HttpClientFactory.CreateClient(api);
            using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, urlstr)
            {
                Content = new StringContent(data, System.Text.Encoding.UTF8, "application/json")
            })
            {
                requestMessage.Headers.Add("u-token", Utoken);

                using (var response = await client.SendAsync(requestMessage).ConfigureAwait(false))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        var result = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                        return result;
                    }
                    throw new HttpRequestException($"{api},{urlstr},{response.StatusCode}");
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="urlstr"></param>
        /// <param name="data"></param>
        /// <param name="api"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        protected async Task<string> PostAsync(string urlstr, string data, string api, CancellationToken cancellationToken)
        {

            var client = HttpClientFactory.CreateClient(api);
            using var requestMessage = new HttpRequestMessage(HttpMethod.Post, urlstr) {
                Content = new StringContent(data, System.Text.Encoding.UTF8, "application/json")
            };
            requestMessage.Headers.Add("u-token", Utoken);

            using var response = await client.SendAsync(requestMessage, cancellationToken).ConfigureAwait(false);
            if (response.IsSuccessStatusCode) {
                var result = await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false);
                return result;
            }
            throw new HttpRequestException($"{api},{urlstr},{response.StatusCode}");
        }
        /// <summary>
        /// 
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="urlstr"></param>
        /// <param name="data"></param>
        /// <param name="api"></param>
        /// <returns></returns>
        protected async Task<T> PostAsync<T>(string urlstr, string data, string api = "mallapi") where T : class
        {
            //var requestMessage = new HttpRequestMessage(HttpMethod.Post, urlstr) {
            //	Content = new StringContent(data, System.Text.Encoding.UTF8, "application/json")
            //};
            //requestMessage.Headers.Add("u-token", Utoken);
            var client = HttpClientFactory.CreateClient(api);
            using (var requestMessage = new HttpRequestMessage(HttpMethod.Post, urlstr) { Content = new StringContent(data, System.Text.Encoding.UTF8, "application/json") })
            {
                requestMessage.Headers.Add("u-token", Utoken);
                using (var response = await client.SendAsync(requestMessage).ConfigureAwait(false))
                {
                    if (response.IsSuccessStatusCode)
                    {
                        var resultStr = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
                        T result = JsonConvert.DeserializeObject<T>(resultStr);
                        return result;
                    }
                    throw new HttpRequestException($"{api},{urlstr},{response.StatusCode}");
                }
            }
        }


        /// <summary>
        /// Posts the third API async.
        /// </summary>
        /// <returns>The third API async.</returns>
        /// <param name="urlstr">URL.</param>
        /// <param name="data">Data.</param>
        /// <param name="api">API.</param>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        protected async Task<BaseResult<T>> PostThirdApiAsync<T>(string urlstr, string data, string api = "mallapi") where T : class
        {
            var ass = await PostAsync<ThirdResult<T>>(urlstr, data, api).ConfigureAwait(false);
            if (ass.IsSuccess)
            {
                return new BaseResult<T>(ass.Data, 0, "");
            }
            if (ass.ResultNo == "02020003")
            {
                BizInfologger.Error($"url:{urlstr},req:{data},rsp:{JsonConvert.SerializeObject(ass)}");
            }
            return new BaseResult<T>(ass.Data, 9999, ass.ResultRemark);
        }

        /// <summary>
        /// Posts the third API with paging async.
        /// </summary>
        /// <returns>The third API with paging async.</returns>
        /// <param name="urlstr">URL.</param>
        /// <param name="data">Data.</param>
        /// <param name="api">API.</param>
        /// <typeparam name="T">The 1st type parameter.</typeparam>
        protected async Task<PagingResultRsp<T>> PostThirdApiWithPagingAsync<T>(string urlstr, string data, string api = "mallapi") where T : class
        {
            var rsp = await PostAsync<ThirdPageingResult<T>>(urlstr, data, api).ConfigureAwait(false);
            if (rsp.IsSuccess)
            {
                return new PagingResultRsp<T>(rsp.Data, rsp.PageIndex, rsp.PageSize, rsp.Total, 0, rsp.ResultRemark);
            }
            return new PagingResultRsp<T>(null, rsp.PageIndex, rsp.PageSize, rsp.Total, 9999, rsp.ResultRemark);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="urlstr"></param>
		/// <param name="data"></param>
		/// <param name="api"></param>
		/// <returns></returns>
		protected async Task<BaseThirdPageingResult<T>> PostThirdApiWithPagingsAsync<T>(string urlstr, string data, string api = "mallapi") where T : class
		{
			var rsp = await PostAsync<ThirdPageingResult<List<T>>>(urlstr, data, api).ConfigureAwait(false);
			if (rsp.IsSuccess) {
				return new BaseThirdPageingResult<T>(rsp.Data, rsp.PageIndex, rsp.PageSize, rsp.Total, 0, rsp.ResultRemark);
			}
			return new BaseThirdPageingResult<T>(null, rsp.PageIndex, rsp.PageSize, rsp.Total, 9999, rsp.ResultRemark);
		}
		/// <summary>
		/// Gets the goods by identifier store identifier.
		/// </summary>
		/// <returns>The goods by identifier store identifier.</returns>
		/// <param name="StoreId">Store identifier.</param>
		/// <param name="GoodsBaseId">Goods base identifier.</param>
		protected async Task<CakeGoodsGetBaseRsp> GetGoodsByIdStoreId(int StoreId, int GoodsBaseId)
        {
            var url = "/CakeMall/v3/Goods/GetGoodsById";
            var data = new { StoreId, GoodsBaseId };
            var rsp = await PostThirdApiAsync<CakeGoodsGetBaseRsp>(url, JsonConvert.SerializeObject(data)).ConfigureAwait(false);

            if (rsp.Code == 0)
            {
                return rsp.Content;
            }
            return null;
        }
        /// <summary>
        /// 外卖运费
        /// </summary>
        /// <param name="OrderMoney"></param>
        /// <returns></returns>
        protected async Task<decimal> CalculateWaimaiOrderFreightMoney(decimal OrderMoney)
        {
            var url = "TakeOut/v1/Index/GetFreightMoney";
            var data = new { OrderMoney };
            var rsp = await PostAsync<ThirdResult<TakeOutGetFreightMoneyRsp>>(url, JsonConvert.SerializeObject(data)).ConfigureAwait(false);
            if (rsp.IsSuccess)
            {
                return rsp.Data.FreightMoney;
            }
            throw new Exception(rsp.ResultRemark);
        }


        /// <summary>
        /// Orders the change status.
        /// </summary>
        /// <returns>The change status.</returns>
        /// <param name="orderCode">Order code.</param>
        /// <param name="mobile">Mobile.</param>
        /// <param name="type">类型 1 支付完成 2 确认收货 3 用户取消订单 4 超时自动取消</param>
        /// <param name="payMethod">支付方式 只有在Type为1 可用</param>
        /// <param name="resBillNo">处理完成单号 只有在Type为1 可用</param>
        protected async Task<string> CakeOrderChangeStatus(string orderCode, string mobile, int type, int payMethod, string resBillNo)
        {
            var url = "CakeMall/v3/Order/ChangeStatus";
            var data = new { orderCode, mobile, type, payMethod, resBillNo };
            var result = await PostAsync(url, JsonConvert.SerializeObject(data)).ConfigureAwait(false);
            return result;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        protected async Task<List<TPPGoodsDrinksSkuIdRsp>> GetDrinkSkus()
        {
            var url = "TPP/v3/Goods/GetDrinksGoodsId";
			// string result = await PostAsync(url, "");
			 
			//var data = await _
            var rsp = await PostThirdApiAsync<List<TPPGoodsDrinksSkuIdRsp>>(url, "").ConfigureAwait(false);
            if (rsp.Code == 0)
            {
                return rsp.Content;
            }
			return new List<TPPGoodsDrinksSkuIdRsp>();
        }

    }
}
